<?php

namespace App\Console\Commands\System\Project;

use App\Models\System\Project\SystemProjectModel;
use App\Models\System\Project\SystemProjectModuleErrorModel;
use App\Models\System\Project\SystemProjectModuleModel;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;

class ProjectModuleErrorGenerateCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'system:projectModuleErrorGenerate';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '系统：生成项目错误码记录';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    public ?SystemProjectModuleModel $systemProjectModuleModel = null;
    public ?SystemProjectModel       $systemProjectModel       = null;

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle(): int
    {
        $systemProject = SystemProjectModel::query()->where("isDeleted", 0)->get();
        if ($systemProject->isEmpty()) {
            $this->error("请先添加项目信息后再重试");
            return parent::FAILURE;
        }
        $systemProjectStr         = $this->getProjectAskStr($systemProject);
        $projectId                = $this->getProjectId($systemProject, $systemProjectStr);
        $this->systemProjectModel = $systemProject->where("id", $projectId)->first();

        $systemProjectModule        = $this->systemProjectModel->moduleRel;
        $systemProjectModuleCurrent = $systemProjectModule->sortBy("id")->values();

        if ($systemProjectModule->isEmpty()) {
            $this->error("请先添加项目模块信息后再重试");
            return parent::FAILURE;
        }
        $systemProjectModuleStr         = $this->getProjectModuleAskStr($systemProjectModuleCurrent);
        $projectModuleId                = $this->getProjectModuleId(
            $systemProjectModuleCurrent,
            $systemProjectModuleStr
        );
        $this->systemProjectModuleModel = $systemProjectModuleCurrent->where("id", $projectModuleId)->first();

        $this->operateAsk();

        $moduleName       = Str::studly(strtolower($this->systemProjectModuleModel->enName));
        $projectEn        = Str::studly(strtolower($this->systemProjectModel->enName));
        $templateContents = view()->file(resource_path(
                "views/system/project") . "/SystemProjectModuleErrorTemplate.blade.php",
            [
                "dateTime"           => date("Y-m-d H:i:s", time()),
                "projectModuleModel" => $this->systemProjectModuleModel,
                "projectModel"       => $this->systemProjectModel,
                "moduleName"         => $moduleName,
                "projectName"        => $projectEn,
                "moduleError"        => SystemProjectModuleErrorModel::query()
                                                                     ->where('projectId', $projectId)
                                                                     ->where("moduleId", $projectModuleId)
                                                                     ->get()
            ]
        )->render();

        $saveDir    = app_path(vsprintf("%s/%s", ["Error", $projectEn]));
        $fileSystem = getFileSystem();
        if (!$fileSystem->isDirectory($saveDir)) {
            $fileSystem->makeDirectory($saveDir, 0777, true);
        }
        $fileSystem->put(
            $saveDir . "/{$moduleName}Error.php",
            vsprintf("%s%s%s", [
                "<?php",
                PHP_EOL,
                $templateContents
            ])
        );
        return parent::SUCCESS;
    }

    public function operateAsk()
    {
        $operateTarget = $this->ask("请选择操作内容 1、 重新生成模块错误码文件  2、 添加选中模块错误码");
        switch ($operateTarget) {
            case 1:
                break;
            case 2:
                $systemProjectModuleError = $this->systemProjectModuleModel->errorRel->sortBy("id")->values();
                $errorKey                 = $this->getAskContent(
                    "错误码 - key",
                    $systemProjectModuleError,
                    true,
                    "errorKey",
                    "/^[a-z|A-Z][a-zA-Z_].*[a-z|A-Z]$/"
                );
                $errorCnDesc              = $this->getAskContent("错误信息（中文）", $systemProjectModuleError);

                if ($systemProjectModuleError->isEmpty()) {
                    $errorCode = 1;
                } else {
                    $errorCode = ((int)$systemProjectModuleError->last()->errorCode) + 1;
                }

                $errorCode = str_pad(
                    $errorCode,
                    3,
                    "0",
                    STR_PAD_LEFT
                );

                $fullCode = vsprintf("%s%s%s", [
                    $this->systemProjectModel->projectCode,
                    $this->systemProjectModuleModel->moduleCode,
                    $errorCode
                ]);
                SystemProjectModuleErrorModel::query()->insertGetId([
                    "fullCode"    => $fullCode,
                    "projectId"   => $this->systemProjectModel->id,
                    "moduleId"    => $this->systemProjectModuleModel->id,
                    "errorKey"    => $errorKey,
                    "errorCnDesc" => $errorCnDesc,
                    "errorCode"   => $errorCode,
                    "createdAt"   => time()
                ]);
                break;
            default:
                $this->error("操作内容选中有误");
                $this->operateAsk();
        }
    }

    /**
     * @param string $askTitle
     * @param Collection $systemProjectModuleError
     * @param bool $checkExists
     * @param string $field
     * @param string $preg
     * @return mixed
     */
    public function getAskContent(
        string $askTitle,
        Collection $systemProjectModuleError,
        bool $checkExists = false,
        string $field = "",
        string $preg = ""
    ) {
        if (empty($askContent = $this->ask(sprintf("请输入 %s", $askTitle)))) {
            $this->error(sprintf("%s 不能为空", $askTitle));
            return $this->getAskContent($askTitle, $systemProjectModuleError, false, $field, $preg);
        }

        if ($preg && !preg_match($preg, $askContent)) {
            $this->error(sprintf("%s 格式不正确（1、子母开头 2、仅包含英文字母和下划线 3、子母结尾）", $askTitle));
            return $this->getAskContent($askTitle, $systemProjectModuleError, false, $field, $preg);
        }

        if ($checkExists && $systemProjectModuleError->where($field, strtoupper($askContent))->first()) {
            $this->error(sprintf("%s 已存在", $askTitle));
            return $this->getAskContent($askTitle, $systemProjectModuleError, false, $field, $preg);
        }

        return strtoupper($askContent);
    }


    /**
     * @param Collection $systemProject
     * @return string
     */
    public function getProjectAskStr(Collection $systemProject): string
    {
        $systemProjectStr = "";
        $systemProject->each(function (SystemProjectModel $systemProjectModel, $key) use (
            &$systemProjectStr,
            $systemProject
        ) {
            $systemProjectStr .= vsprintf(" %s、 %s %s", [
                $systemProjectModel->id,
                $systemProjectModel->cnName,
                count($systemProject) == $key + 1 ? "" : PHP_EOL
            ]);
        });
        return $systemProjectStr;
    }

    /**
     * @param Collection $systemProject
     * @param string $systemProjectStr
     * @param bool $errorInput
     * @return mixed
     */
    public function getProjectId(Collection $systemProject, string $systemProjectStr, bool $errorInput = false)
    {
        if ($errorInput) {
            $this->error("输入有误");
        }
        $projectId = $this->ask(vsprintf("请选择以下项目， 输入对应数字 %s%s", [
            PHP_EOL,
            rtrim($systemProjectStr)
        ]));
        if ($systemProject->where("id", $projectId)->isEmpty()) {
            return $this->getProjectId($systemProject, $systemProjectStr, true);
        }
        return $projectId;
    }

    /**
     * @param Collection $systemProjectModule
     * @return string
     */
    public function getProjectModuleAskStr(Collection $systemProjectModule): string
    {
        $systemProjectModuleStr = "";
        $systemProjectModule->each(function (SystemProjectModuleModel $systemProjectModuleModel, $key) use (
            &$systemProjectModuleStr,
            $systemProjectModule
        ) {
            $systemProjectModuleStr .= vsprintf(" %s、 %s %s", [
                $systemProjectModuleModel->id,
                $systemProjectModuleModel->cnName,
                count($systemProjectModule) == $key + 1 ? "" : PHP_EOL
            ]);
        });
        return $systemProjectModuleStr;
    }

    /**
     * @param Collection $systemProjectModule
     * @param string $systemProjectModuleStr
     * @param bool $errorInput
     * @return mixed
     */
    public function getProjectModuleId(
        Collection $systemProjectModule,
        string $systemProjectModuleStr,
        bool $errorInput = false
    ) {
        if ($errorInput) {
            $this->error("输入有误");
        }
        $projectId = $this->ask(vsprintf("请选择以下模块， 输入对应数字 %s%s", [
            PHP_EOL,
            rtrim($systemProjectModuleStr)
        ]));
        if ($systemProjectModule->where("id", $projectId)->isEmpty()) {
            return $this->getProjectId($systemProjectModule, $systemProjectModuleStr, true);
        }
        return $projectId;
    }
}
